package controller;

import model.Disciplina;
import java.sql.ResultSet;
import java.util.ArrayList;

/**
 * Classe que representa um Data Access Object para acessar/modificar a tabela DISCIPLINA
 * do banco de dados do SADAF
 * Esta classe segue o padrão SINGLETON.
 * @author Adriano
 * @see http://en.wikipedia.org/wiki/Singleton_pattern
 */
public class DisciplinaDAO {

    // Instância do DisciplinaDAO.
    private static final DisciplinaDAO INSTANCE = new DisciplinaDAO();
    
    // Instância única da lista de Alunos
    private ArrayList<Disciplina> listaDeDisciplinas;

    // Construtor privado para que outras classes não instanciem o DisciplinaDAO
    private DisciplinaDAO() {
        this.listaDeDisciplinas = this.montarListaDeDisciplinas();
    }

    /**
     * O acesso ao objeto DisciplinaDAO deve ser feito através do método getInstance.
     * Isto garante apenas uma instância de DisciplinaDAO.
     */
    public static DisciplinaDAO getInstance() {
        return INSTANCE;
    }

     /**
     * Retorna a lista de disciplinas
     * @return
     */
    public ArrayList<Disciplina> getListaDeDisciplinas() {
        return this.listaDeDisciplinas;
    }

    /**
     * Cadastra uma disciplina no banco de dados do SADAF.
     * @param disciplina Disciplina a ser cadastrado.
     */
    public void cadastrar(Disciplina disciplina) {

        BancoDeDados bd = new BancoDeDados();

        try {
            bd.carregarDriver();
            bd.conectar(bd.bdUrl, bd.bdUsuario, bd.bdSenha);
            bd.sql = "INSERT INTO DISCIPLINA "
                    + "(CODIGO, "
                    + "NOME) "
                    + "VALUES (?, ?)";
            bd.comandoSql = bd.connection.prepareStatement(bd.sql);
            bd.comandoSql.setString(1, disciplina.getCodigo());
            bd.comandoSql.setString(2, disciplina.getNome());
            bd.comandoSql.executeUpdate();
            bd.desconectar();
            this.listaDeDisciplinas.add(disciplina);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Efetua um acesso na tabela de DISCIPLINA e retorna uma lista de Disciplinas
     * cadastrados no banco de dados do SADAF.
     * Método utilizado para montar/atualizar a listaDeDisciplinas do DAO.
     * @return ArrayList<Disciplina> contendo todas as disciplinas do bd.
     */
    private ArrayList<Disciplina> montarListaDeDisciplinas() {

        ArrayList<Disciplina> retArray = new ArrayList<Disciplina>();
        BancoDeDados bd                = new BancoDeDados();

        try {
            bd.carregarDriver();
            bd.conectar(bd.bdUrl, bd.bdUsuario, bd.bdSenha);
            bd.sql        = "SELECT * FROM DISCIPLINA";
            bd.comandoSql = bd.connection.prepareStatement(bd.sql);
            ResultSet rs  = bd.comandoSql.executeQuery();

            while (rs.next()) {
                String codigoDisciplina = rs.getString(1);
                String nomeDisciplina   = rs.getString(2);
                Disciplina disciplina   = new Disciplina(codigoDisciplina, nomeDisciplina);
                retArray.add(disciplina);
            }
            bd.desconectar();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return retArray;
    }

    /**
     * Exclui uma Disciplina do banco de dados do SADAF.
     * @param disciplina Disciplina que vai ser excluído.
     */
    public void excluir(Disciplina disciplina) {

        BancoDeDados bd = new BancoDeDados();

        try {

            bd.carregarDriver();
            bd.conectar(bd.bdUrl, bd.bdUsuario, bd.bdSenha);
            bd.sql        = "DELETE FROM DISCIPLINA WHERE CODIGO = ?";
            bd.comandoSql = bd.connection.prepareStatement(bd.sql);
            bd.comandoSql.setString(1, disciplina.getCodigo());
            bd.comandoSql.executeUpdate();
            bd.desconectar();

            // remove a disciplina da lista de disciplinas.
            int tamanhoListaDeDisciplinas = this.listaDeDisciplinas.size();
            for (int i = 0; i < tamanhoListaDeDisciplinas; i++) {
                if (this.listaDeDisciplinas.get(i).getCodigo().equals(disciplina.getCodigo())) {
                    this.listaDeDisciplinas.remove(i);
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Procura na lista de disciplinas do banco aquela cujo código é igual ao
     * passado por parâmetro.
     * @param codigo Chave primária de busca.
     * @return Objeto Disciplina ou null caso não encontre.
     */
    public Disciplina ProcuraDisciplina(String codigo) {

        Disciplina retDisciplina      = null;
        int tamanhoListaDeDisciplinas = this.listaDeDisciplinas.size();

        for (int i = 0; i < tamanhoListaDeDisciplinas; i++) {
            if (this.listaDeDisciplinas.get(i).getCodigo().equals(codigo)) {
                retDisciplina = this.listaDeDisciplinas.get(i);
                break;
            }
        }

        return retDisciplina;
    }
}
